package lac.serviceuint.tool;

import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import lac.serviceuint.ServiceUnitContext;

public class HttpUtil {

	private static Logger log = LoggerFactory.getLogger(HttpUtil.class);
	public static ObjectMapper objectMapper = new ObjectMapper();
	
	static{
		objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
	}
	
	public static CloseableHttpClient httpClient = HttpClients.custom()
    		.setConnectionManager(newConnectionManager())
    		.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
    		.build();
	
	public static Object httpPostServiceUnitRequest(String url,List<Object> params){
		HttpResponse httpResponse = null;
		try {
			HttpPost httpPost = new HttpPost(url);
			Map<String,Object> sessionInfo = ServiceUnitContext.getCurrentVar("sessionInfo",Map.class);
			if(sessionInfo != null){
				String token = sessionInfo.get("token")==null?null:sessionInfo.get("token").toString();
				if(token != null){
					BasicHeader header = new BasicHeader("token",token);
					httpPost.setHeader(header);
				}
			}
			HttpEntity requestEntity = new StringEntity(objectMapper.writeValueAsString(params), ContentType.APPLICATION_JSON);
			httpPost.setEntity(requestEntity);
			log.info("request:"+httpPost.toString());
			httpResponse =  httpClient.execute(httpPost);
			log.info("response:"+httpResponse.getStatusLine().toString());
			HttpEntity responseEntity = httpResponse.getEntity();
			String responseMsg = EntityUtils.toString(responseEntity);
			log.debug("response message:"+responseMsg);
			Map<String,Object> context = objectMapper.readValue(responseMsg, Map.class);
			if(context.get("success")!=null && (Boolean)context.get("success")){
				return context.get("data");
			}else{
				String exceptionStackTrace = context.get("exceptionStackTrace")==null?null:context.get("exceptionStackTrace").toString();
				log.error(exceptionStackTrace);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return false;
	}
	
	private static final CloseableHttpClient newClient() {
        HttpClientBuilder builder = HttpClientBuilder.create();
        builder.setConnectionManager(newConnectionManager());
        builder.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
        builder.setRedirectStrategy(new RedirectStrategy() {
			public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context)
					throws ProtocolException {
				return false;
			}

			public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context)
					throws ProtocolException {
				return null;
			}
        });
        return builder.build();
    }

	private static final HttpClientConnectionManager newConnectionManager() {
		SSLContext sslContext = SSLContexts.createSystemDefault();

		Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
				.register("http", PlainConnectionSocketFactory.INSTANCE)
				.register("https", new SSLConnectionSocketFactory(sslContext)).build();

		PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(
				socketFactoryRegistry);
		connectionManager.setMaxTotal(200);
		connectionManager.setDefaultMaxPerRoute(20);
		return connectionManager;
	}
}
